package logic

import (
	"fmt"
	"github.com/gogap/logs"
	"github.com/shopspring/decimal"
	"sort"
	"strings"
	"yundian/internel/app/dao"
	"yundian/internel/app/helper"
	"yundian/internel/app/models/devices"
	"yundian/internel/app/models/orders"
	"yundian/internel/app/models/users"
	"yundian/internel/pkg/dbs"
)

// ----------------- 异步操作任务 ----------------------- //

// CalOrderDividends 计算订单分红
func (logic *OrderLogic) CalOrderDividends(param ...interface{}) {
	orderInfo := param[0].(*orders.OrderModel)
	devInfo := param[1].(*devices.DeviceType)
	settMoney := param[2].(int64)
	endTime := param[3].(int64)

	// todo 参数校验
	if orderInfo == nil || orderInfo.Id == 0 {
		logs.Error("CalOrderDividends: 订单信息数据错误，无法执行分红")
		return
	}
	if settMoney == 0 {
		logs.Error("CalOrderDividends: 分红金额数据错误，无法执行分红")
		return
	}
	if devInfo == nil {
		devInfo = dao.NewDeviceDao().FetchDeviceInfoWithType(orderInfo.DeviceSn).Unwrap().(*devices.DeviceType)
	}
	if endTime == 0 {
		endTime = int64(orderInfo.EndAt)
	}

	// todo 用户信息校验
	var userInfo *users.UserModel
	if orderInfo.IsDraw == helper.TypeNumIsDrawOpen {
		if orderInfo.AgentUserId <= 0 {
			logs.Error("CalOrderDividends->orderInfo.AgentUserId: 数据错误，无法执行分红", orderInfo)
			return
		}
		if userInfo = dao.NewUserDao().GetUserInfoById(orderInfo.AgentUserId).Unwrap().(*users.UserModel); userInfo.ID == 0 {
			logs.Error("CalOrderDividends->GetUserInfoById: 数据错误，无法执行分红", orderInfo)
			return
		}
	} else {
		if userInfo = dao.NewUserDao().GetUserInfoByPlaceId(orderInfo.PlaceId).Unwrap().(*users.UserModel); userInfo.ID == 0 {
			logs.Error("CalOrderDividends->GetUserInfoByPlaceId: 数据错误，无法执行分红", orderInfo)
			return
		}
	}

	// todo 首单校验
	firstPclOrder := dao.NewOrderDao().GetOrderFirstByPlaceIdAndDeviceSn(orderInfo.PlaceId, orderInfo.DeviceSn)
	// logs.Info("首单用户信息", firstPclOrder, firstPclOrder.IsOpenFirst, firstPclOrder.Id, orderInfo.Id)
	if firstPclOrder.IsOpenFirst == 1 && firstPclOrder.Id == orderInfo.Id {
		userInfo = dao.NewUserDao().GetUserInfoById(2).Unwrap().(*users.UserModel)
	}

	// todo 分红
	count := dao.NewOrderDao().CountDividendsLogsByTradeNo(orderInfo.TradeNo, userInfo.ID).Unwrap().(int64)
	if count == 0 {
		logic.CalAgentBonus(userInfo, orderInfo, devInfo, settMoney, 0, endTime)
	}
}

// CalAgentBonus 代理商分红
func (logic *OrderLogic) CalAgentBonus(curruserInfo *users.UserModel, orderInfo *orders.OrderModel, devInfo *devices.DeviceType, settMoney, profit int64, endTime int64) {

	var err error
	var userList []*users.UserModel
	userList = append(userList, curruserInfo)

	if userList, err = QueryParentListAll(curruserInfo, userList, 0); err != nil {
		logs.Error("CalAgentBonus->QueryParentListAll", err)
		return
	}

	// todo 门店关联分公司参与分红
	if orderInfo.IsDraw != helper.TypeNumIsDrawOpen {
		branchUserInfo := dao.NewUserDao().GetBranchUserInfoByPlaceId(orderInfo.PlaceId).Unwrap().(*users.UserModel)
		if branchUserInfo.ID > 0 && orderInfo.AgentUserId != branchUserInfo.ID {
			userList = append(userList, branchUserInfo)
		}
	}

	// todo 排序
	userList = repetitionUserList(userList)
	sort.Slice(userList, func(i, j int) bool {
		if userList[i].ProfitProportion != userList[j].ProfitProportion {
			return userList[i].ProfitProportion < userList[j].ProfitProportion
		}
		IsAdmins := fmt.Sprintf("[%d][%d][%d][%d][%d][%d][%d][%d][%d][%d]",
			helper.TypeNumIsAdminMerchant, helper.TypeNumIsAdminBd, helper.TypeNumIsAdminKaProject, helper.TypeNumIsAdminRegion, helper.TypeNumIsAdminResource,
			helper.TypeNumIsAdminStaff, helper.TypeNumIsAdminPartner, helper.TypeNumIsAdminBranch, helper.TypeNumIsAdminOperator, helper.TypeNumIsAdminAdministrator)
		iIndex := strings.Index(IsAdmins, fmt.Sprintf("[%d]", userList[i].IsAdmin))
		jIndex := strings.Index(IsAdmins, fmt.Sprintf("[%d]", userList[j].IsAdmin))
		return iIndex < jIndex
	})

	// todo 分红
	tx, key := dbs.GormBegin("CalAgentBonus")
	for index, item := range userList {
		if index > 0 {
			profit = int64(userList[index-1].ProfitProportion)
		}
		lastProfit := decimal.NewFromInt(int64(profit))
		curruserProfit := decimal.NewFromInt(int64(item.ProfitProportion))
		sett := decimal.NewFromInt(settMoney)
		money := curruserProfit.Sub(lastProfit).Mul(sett).Div(decimal.NewFromInt(100))

		// 添加分红记录
		if err = logic.InsertRewardLog(tx, item, orderInfo, devInfo, settMoney, money, endTime); err != nil {
			dbs.GormRollback(tx, key, err)
			return
		}
	}
	dbs.GormCommit(tx, key)
}